import pygame
from pygame.locals import *

from constants import *
from obstacle import *

class Level:
	"""Contains information about a location in the game.
	-- Class variables --
	obstacles    : object[][]  : Matrix of the objects in the level.
	access       : boolean[][] : Matrix of positions in the level, accessible or not to the character.
	passages     : dictionnary : {(x_position, y_position): (destination_mapFile, x_destination, y_destination)}
	background   : Pygame      : Filling the blanks in the game window.
	border       : Pygame      : Filling the surrounginds of the map to prevent from going far far away!
	-- Class public methods --
	load                   : None         : Converts data from file into the Level object.
	loadSize               : string       : Creates a matrix large enough to contain the world, delimited by a border. Returns the line following the size section.
	loadBackground         : string       : Initializes the background picture for the level. Returns the line following the background section.
	loadBorder             : string       : Initializes the filename of the border image. Returns the line following the border section.
	loadProperties         : string       : Creates a dictionnary of the properties of the elements on the map. Returns the line following the properties section.
	loadObstaclesAndAccess : string       : Fills the obstacles and access matrices with the level's elements and properties. Returns the line following the section.
	loadPassages           : string       : Creates a dictionnary of the passages toward other levels. Returns the line following the passages section.
	displayBackground      : None         : Fills the main window with background images.
	getSurroundings        : obstacle[][] : Returns the obstacles.in a delimited perimeter around the character.
	diplaySurroundings     : None         : Diplays the elements visible in the window frame.
	"""
	def __init__(self, mapFile):
		self.obstacles = []
		self.access = []
		self.passages = {}
		self.background = None
		self.border = None
		self.load(mapFile)

	def load(self, filename):
		"""Imports data from a file into the Level object. Sets the "obstacles", "access", and "passages" values accordingly.
		-- Inputs --
		filename     : string   :  File containing the level data.
		-- Outputs --
		None
		"""
		f = open(filename)
		line = f.readline().strip()
		while (line != ''):
			if (line == FileBorderSection):
				line = self.loadBorder(f)
			elif (line == FileSizeSection):
				line = self.loadSize(f)
			elif (line == FileBackgroundSection):
				line = self.loadBackground(f)
			elif (line == FilePropertiesSection):
				(line,properties) = self.loadProperties(f) # utiliser properties et obstacles pour construire access
			elif (line == FileObstaclesSection):
				line = self.loadObstaclesAndAccess(f, properties)
			elif (line == FilePassagesSection):
				line = self.loadPassages(f)
			else :
				line = f.readline().strip()
		f.close()
		return

	def loadSize(self, f):
		"""Imports the size of the map and initializes consequently the access and obstacles matrices.
		-- Inputs --
		f       : Stream    : Stream from the map file.
		-- Outputs --
		line    : string    : Next header read.
		"""
		line = f.readline().split('\t')
		for x in range(int(line[0])):
			self.obstacles.append([])
			self.access.append([])
			for y in range(int(line[1])):
				self.obstacles[x].append(None)
				self.access[x].append(True)
		for x in range(0, SightLeft):
			for y in range(int(line[1])):
				self.access[x][y] = False
				self.obstacles[x][y] = Obstacle(self.border)
		for x in range(int(line[0])-SightRight, int(line[0])):
			for y in range(int(line[1])):
				self.access[x][y] = False
				self.obstacles[x][y] = Obstacle(self.border)
		for x in range(SightLeft, int(line[0])-SightRight):
			for y in range(SightUp):
				self.access[x][y] = False
				self.obstacles[x][y] = Obstacle(self.border)
			for y in range(int(line[1])-SightDown, int(line[1])):
				self.access[x][y] = False
				self.obstacles[x][y] = Obstacle(self.border)
		line = f.readline().strip()
		return line

	def loadBackground(self, f):
		"""Imports the background sprite of the map.
		-- Inputs --
		f       : Stream    : Stream from the map file.
		-- Outputs --
		line    : string    : Next header read.
		"""
		line = f.readline().strip()
		self.background = pygame.image.load(eval(line)).convert()
		line = f.readline().strip()
		return line

	def loadBorder(self, f):
		"""Imports the border sprite of the map.
		-- Inputs --
		f       : Stream    : Stream from the map file.
		-- Outputs --
		line    : string    : Next header read.
		"""
		line = f.readline().strip()
		self.border = eval(line)
		line = f.readline().strip()
		return line

	def loadProperties(self, f):
		"""Imports the properties of the obstacles in the map.
		-- Inputs --
		f          : Stream      : Stream from the map file.
		-- Outputs --
		line       : string      : Next header read.
		properties : dictionnary : Dictionnary, key=ObstacleName, value=ObstacleProperties
		"""
		properties = {}
		line = f.readline().strip()
		while (line[0] != '/'):
			line = line.split('\t')
			properties[line[0]] = (int(line[1]), int(line[2]), bool(int(line[3])))
			line = f.readline().strip()
		return (line,properties)

	def loadObstaclesAndAccess(self, f, properties):
		"""Imports the obstacles and their localization in the map.
		-- Inputs --
		f          : Stream      : Stream from the map file.
		properties : dictionnary : Dictionnary, key=ObstacleName, value=ObstacleProperties
		-- Outputs --
		line       : string      : Next header read.
		"""
		line = f.readline()
		while (line[0] != '/'):
			line = line.split('\t')
			self.obstacles[int(line[1])][int(line[2])] = Obstacle(eval(line[0]))
			for x in range(int(line[1]), int(line[1])+properties[line[0]][0]):
				for y in range(int(line[2]), int(line[2])+properties[line[0]][1]):
					self.access[x][y] = properties[line[0]][2]
			line = f.readline().strip()
		return line

	def loadPassages(self, f):
		"""Imports the passages, their localization in the map, and their destination.
		-- Inputs --
		f          : Stream      : Stream from the map file.
		-- Outputs --
		line       : string      : Next header read.
		"""
		line = f.readline().strip()
		while (line != ''):
			line = line.split('\t')
			self.passages[(int(line[0]),int(line[1]))] = (line[2],int(line[3]),int(line[4]))
			line = f.readline().strip()
		return line

	def displayBackground(self, window):
		"""Fills the game window with background sprites.
		-- Inputs --
		window     : Pygame      : Main window.
		-- Outputs --
		None
		"""
		for x in range(WindowDefaultWidth/SpriteWidth):
			for y in range (WindowDefaultHeigth/SpriteHeigth):
				window.blit(self.background, (x*SpriteWidth, y*SpriteHeigth))
		return

	def getSurroundings(self, x_position, y_position):
		"""Returns the obstacles in the area around the character.
		-- Inputs --
		x_position     : integer     : Coordinate of the character on the first axis.
		y_position     : integer     : Coordinate of the character on the second axis.
		-- Outputs --
		matrix         : objects[][] : Matrix of Obstacles/None in the surrounding area.
		"""
		matrix = []
		i = 0
		for x in range(x_position-SightLeft, x_position+SightRight+1):
			matrix.append([])
			for y in range(y_position-SightUp, y_position+SightDown+1):
				matrix[i].append(self.obstacles[x][y])
			i+=1
		return matrix

	def diplaySurroundings(self, window, surroundings):
		"""Fills the game window with the surrouding obstacles.
		-- Inputs --
		window           : Pygame      : Main window of the game.
		surroundings     : objects[][] : Coordinate of the character on the second axis.
		-- Outputs --
		None
		"""
		for x in range(len(surroundings)):
			for y in range(len(surroundings[0])):
				if (surroundings[x][y]):
					window.blit(surroundings[x][y].sprite, (x*SpriteWidth, y*SpriteHeigth))
		return

